package nl.utwente.ewi.hmi.multitouch.example;

import java.util.List;

import nl.utwente.ewi.hmi.multitouch.Touch;
import nl.utwente.ewi.hmi.multitouch.TouchDevice;
import nl.utwente.ewi.hmi.multitouch.TouchDeviceAdapter;
import nl.utwente.ewi.hmi.multitouch.TouchDeviceInfo;
import nl.utwente.ewi.hmi.multitouch.TouchEnvironment;
import nl.utwente.ewi.hmi.multitouch.drivers.diamondtouch.DiamondTouchStreamProvider;
import nl.utwente.ewi.hmi.multitouch.drivers.mouse.MouseTouchStreamProvider;
import nl.utwente.ewi.hmi.multitouch.drivers.tuio.TuioTouchStreamProvider;
import nl.utwente.ewi.hmi.multitouch.event.TouchAdapter;
import nl.utwente.ewi.hmi.multitouch.event.TouchEvent;
import nl.utwente.ewi.hmi.multitouch.io.TouchDeviceException;
import nl.utwente.ewi.hmi.multitouch.io.TouchStreamProvider;

/**
 * This class is a quick example on how to get things going using the multi-touch framework.
 *  
 * @author Michiel Hakvoort
 * @version 1.0
 */
public class TouchExample {

	
	
	public static void main(String[] args) {
		boolean useTheDiamondTouchTableInThisExample = false;
		
		// Get the TouchEnvironment first (a central managing mechanism for TouchDevices)
		TouchEnvironment environment = TouchEnvironment.getTouchEnvironment();
		
		// The TouchStreamProvider provides TouchStream which in turn can be wrapped inside
		// a TouchDevice. The TouchDevice is an abstraction for multi-touch interaction, but
		// we'll get there later.
		TouchStreamProvider provider;

		// If we use the DiamondTouch table in this example ..
		if(useTheDiamondTouchTableInThisExample) {
			// .. retrieve the DiamondTouch provider ..
			provider = DiamondTouchStreamProvider.getDiamondTouchStreamProvider();	
		} else {
			// .. else revert to the mouse
			provider = new TuioTouchStreamProvider(3099);
		}
		
		// Hook the provider in the environment, after this we can search all available devices through the environment 
		environment.registerTouchStreamProvider(provider);

		// And we do that like this ..
		List<TouchDeviceInfo> infoList = environment.getTouchDeviceInfoList();
		
		// Next we get the first TouchDeviceInfo, here we make the assumption !infoList.isEmpty()
		TouchDeviceInfo info = infoList.get(0);
		
		// If you want to know which device we're going to use, use info.getDeviceID();
		
		// Get the TouchDevice for the TouchDeviceInfo, again using the TouchEnvironment
		TouchDevice device = environment.getTouchDevice(info);

		// Now we can hook a listener into the TouchDevice, here we'll hook a an anonymous TouchDeviceAdapter into it, which
		// releases a lock so this TouchExample can exit
		final Object object = new Object();
		
		device.addTouchDeviceListener(new TouchDeviceAdapter() {
			public void touchDeviceStopped(TouchDevice touchDevice) {
				synchronized(object) {
					object.notifyAll();
				}
			}
		});
		
		// Now we add another listener which will tell us when the TouchDevice has stopped or started 
		device.addTouchDeviceListener(new TouchDeviceAdapter() {
			public void touchDeviceStarted(TouchDevice touchDevice) {
				System.out.println(touchDevice.getTouchDeviceInfo().getDeviceID() + " was started.");
			}
			public void touchDeviceStopped(TouchDevice touchDevice) {
				System.out.println(touchDevice.getTouchDeviceInfo().getDeviceID() + " was stopped.");
			}
		});

		// Now we're going to listen for touches as well (mind you that all this can be done in one listener
		// but to demonstrate the concept we'll use multiple listeners
		device.addTouchDeviceListener(new TouchDeviceAdapter() {
			public void touchRegistered(TouchDevice touchDevice, Touch touch) {
				System.out.println("registered!");
				// We can immediately add a listener to the touch
				touch.addTouchListener(new TouchAdapter() {
					
					// And just listen to when a Touch gets released
					public void touchReleased(TouchEvent event) {
						
						
						System.out.println("A touch was released at "
								+ event.getSource().getOrigin());
					}
				});
				
			}
		});

		// Finally start the device
		try {
			device.start();
		} catch (TouchDeviceException e) {
			e.printStackTrace();
			System.exit(1);
		}

		System.out.println("As can be seen, read events are now called from a different thread");

		// If no threads are registered as non daemons, this lock will prevent the application from closing 
		synchronized(object) {
			try {
				// This will block forever, until released
				object.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

}
